package com.witmore.neutron.ai.web.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jk.common.enums.WitmoreErrorCode;
import com.jk.common.exception.WitmoreException;
import com.jk.common.utils.JwtUtil;
import com.witmore.neutron.ai.db.entity.UserDO;
import com.witmore.neutron.ai.db.entity.UserRechargeRecordDO;
import com.witmore.neutron.ai.db.mapper.UserMapper;
import com.witmore.neutron.ai.db.mapper.UserRechargeRecordMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import com.witmore.neutron.ai.web.apiv2.controller.vo.ProviderEmployeeResult;
import com.witmore.neutron.ai.web.apiv2.controller.vo.RoleUserResult;
import com.witmore.neutron.ai.web.controller.vo.UserSession;
import com.witmore.neutron.ai.web.service.*;
import com.witmore.neutron.ai.web.wechat.dto.WechatUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;

/**
 * Description: UserSessionUtil
 * Author: 豆子高
 * Date: 2025/9/3 17:35
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRechargeRecordMapper userRechargeRecordMapper;
    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private ProviderProfileService providerProfileService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private UserRoleBindingService userRoleBindingService;

    @Value("${witmore.session.new-user-times:50}")
    private Integer newUserTimes;

    @Value("${witmore.session.bind-wxchat-times:50}")
    private Integer bindWxchatTimes;

    @Override
    public UserSession setUserSession(Integer userId) {
        UserDO userDO = userMapper.selectById(userId);
        if (userDO == null) {
            log.error("用户不存在，userId: {}", userId);
            throw new WitmoreException(WitmoreErrorCode.USER_NOT_EXIST);
        }
        return setUserSession(userDO);
    }
    @Override
    public UserSession setUserSession(UserDO userDO) {
        UserSession userSession = new UserSession();
        BeanUtils.copyProperties(userDO, userSession);

        // 生成 JWT Token
        String token = jwtUtil.generateToken(JSONObject.toJSONString(userSession));
        token = URLEncoder.encode(token, StandardCharsets.UTF_8);
        userSession.setToken(token);
        userSession.setWxOpenid(userDO.getWxOpenid());
        // 查询服务商信息
        try {
            ProviderEmployeeResult providerInfo = providerProfileService.getUserProviderInfo(userDO.getId());
            userSession.setProviderProfile(providerInfo);
        } catch (Exception e) {
            // 查询服务商信息失败不影响登录，只记录日志
            // 可能用户还没有关联任何服务商
        }
        // 组装角色权限
        if (!userDO.getIsSuperAdmin()) {
            List<RoleUserResult> roleByUserId = roleService.getRoleByUserId(userDO.getId().longValue());
            userSession.setRoles(roleByUserId);
            userSession.setRoleIds(roleService.getRoleIdsByUserId(userDO.getId().longValue()));
            userSession.setRoleType(CollectionUtils.isEmpty(roleByUserId) ? null : roleByUserId.get(0).getRoleType());
            // 权限并集
            userSession.setPermissions(permissionService.getPermissionsByUserId(userDO.getId().longValue()));
            userSession.setPermissionCodes(permissionService.getPermissionNamesByUserId(userDO.getId().longValue()));
        }
        return userSession;
    }

    @Override
    public UserDO createNewUserNormal(UserDO newUser) {
        try {
            newUser.setActiveStatus((byte) 1);
            newUser.setRegisterTime(LocalDateTime.now());
            newUser.setCreateTime(LocalDateTime.now());
            newUser.setUpdateTime(LocalDateTime.now());
            newUser.setIsSuperAdmin(false);
            newUser.setSessionTotalTimes(newUserTimes);
            newUser.setSessionRemainingTimes(newUserTimes);
            int result = userMapper.insert(newUser);
            if (result > 0) {
                // 为新注册用户自动绑定普通用户角色
                try {
                    userRoleBindingService.bindNormalUserRole(newUser.getId().longValue(), null);
                    log.info("成功为新注册用户{}绑定普通用户角色", newUser.getId());
                } catch (Exception e) {
                    log.error("为新注册用户{}绑定普通用户角色失败", newUser.getId(), e);
                    // 角色绑定失败不影响用户注册，只记录日志
                }

                // 创建新用户充值记录
                createRechargeRecord(newUser, newUserTimes);

                return newUser;
            }
            return null;
        } catch (Exception e) {
            log.error("创建用户失败，newUser：{}", newUser, e);
            return null;
        }
    }

    @Override
    public UserBindResult bindUserOpenid(UserDO targetUser, WechatUserInfo wechatUserInfo) {
        try {
            // 验证参数
            if (targetUser == null || wechatUserInfo == null || !StringUtils.hasText(wechatUserInfo.getOpenid())) {
                return new UserBindResult(false, "参数不能为空");
            }

            String newOpenid = wechatUserInfo.getOpenid();

            // 校验目标用户是否已绑定手机号
            if (!StringUtils.hasText(targetUser.getUserPhone())) {
                return new UserBindResult(false, "用户未绑定手机号，无法绑定微信");
            }

            // 检查目标用户是否已经绑定了微信
            if (StringUtils.hasText(targetUser.getWxOpenid())) {
                // 如果已绑定，检查openid是否相等
                if (newOpenid.equals(targetUser.getWxOpenid())) {
                    // 即使已绑定同一个微信，也要更新昵称和头像信息
                    boolean updated = false;

                    // 更新用户昵称（如果微信昵称有变化）
                    if (StringUtils.hasText(wechatUserInfo.getNickname()) &&
                            !wechatUserInfo.getNickname().equals(targetUser.getNickName())) {
                        targetUser.setNickName(wechatUserInfo.getNickname());
                        updated = true;
                    }

                    // 更新用户头像（如果微信头像有变化）
                    if (StringUtils.hasText(wechatUserInfo.getHeadImgUrl()) &&
                            !wechatUserInfo.getHeadImgUrl().equals(targetUser.getAvatarUrl())) {
                        targetUser.setAvatarUrl(wechatUserInfo.getHeadImgUrl());
                        updated = true;
                    }

                    if (updated) {
                        targetUser.setUpdateTime(LocalDateTime.now());
                        userMapper.updateById(targetUser);
                        log.info("更新已绑定用户的微信信息: userId={}, nickname={}, avatar={}",
                                targetUser.getId(), wechatUserInfo.getNickname(), wechatUserInfo.getHeadImgUrl());
                        return new UserBindResult(true, "用户信息已更新", targetUser);
                    } else {
                        return new UserBindResult(true, "用户已绑定该微信账号，信息无变化", targetUser);
                    }
                } else {
                    return new UserBindResult(false, "用户已绑定其他微信账号");
                }
            }

            // 检查新的openid是否已被其他用户绑定
            UserDO existingUser = userMapper.selectOne(new LambdaQueryWrapper<UserDO>()
                    .eq(UserDO::getWxOpenid, newOpenid)
                    .ne(UserDO::getId, targetUser.getId()));

            if (existingUser != null) {
                return new UserBindResult(false, "该微信账号已被其他用户绑定");
            }

            // 执行绑定操作并更新用户信息
            targetUser.setWxOpenid(newOpenid);

            // 更新用户昵称
            if (StringUtils.hasText(wechatUserInfo.getNickname())) {
                targetUser.setNickName(wechatUserInfo.getNickname());
            }

            // 更新用户头像
            if (StringUtils.hasText(wechatUserInfo.getHeadImgUrl())) {
                targetUser.setAvatarUrl(wechatUserInfo.getHeadImgUrl());
            }

            // 增加绑定微信的会话次数
            int beforeRemainingTimes = targetUser.getSessionRemainingTimes() != null ?
                targetUser.getSessionRemainingTimes() : 0;
            Integer afterRemainingTimes = beforeRemainingTimes + bindWxchatTimes;
            targetUser.setSessionRemainingTimes(afterRemainingTimes);

            targetUser.setUpdateTime(LocalDateTime.now());

            int result = userMapper.updateById(targetUser);
            if (result > 0) {
                // 创建绑定微信充值记录
                createRechargeRecord(targetUser, bindWxchatTimes, "绑定微信账号奖励", null, "系统",
                    beforeRemainingTimes, afterRemainingTimes);

                log.info("微信openid绑定成功并更新用户信息: userId={}, openId={}, nickname={}, avatar={}, 奖励次数={}",
                        targetUser.getId(), newOpenid, wechatUserInfo.getNickname(), wechatUserInfo.getHeadImgUrl(), bindWxchatTimes);
                return new UserBindResult(true, "微信账号绑定成功，用户信息已更新", targetUser);
            } else {
                log.error("数据库更新失败，userId: {}, openId: {}", targetUser.getId(), newOpenid);
                return new UserBindResult(false, "微信账号绑定失败");
            }

        } catch (Exception e) {
            log.error("绑定微信openid并更新用户信息异常，userId: {}, openId: {}",
                    targetUser != null ? targetUser.getId() : "null",
                    wechatUserInfo != null ? wechatUserInfo.getOpenid() : "null", e);
            return new UserBindResult(false, "绑定异常: " + e.getMessage());
        }
    }

    /**
     * 创建用户充值记录
     */
    private void createRechargeRecord(UserDO user, Integer sessionTimes) {
        createRechargeRecord(user, sessionTimes, "新用户注册赠送", null, "系统", null, null);
    }

    /**
     * 创建用户充值记录（带前后剩余次数）
     */
    @Override
    public void createRechargeRecord(UserDO user, Integer sessionTimes, String operationDesc, Integer operatorId, String operatorName,
                                     Integer beforeRemainingTimes, Integer afterRemainingTimes) {
        createRechargeRecord(user, sessionTimes, operationDesc, operatorId, operatorName, beforeRemainingTimes, afterRemainingTimes, 1);
    }

    /**
     * 创建用户充值/扣款记录（带前后剩余次数和操作类型）
     */
    @Override
    public void createRechargeRecord(UserDO user, Integer sessionTimes, String operationDesc, Integer operatorId, String operatorName,
                                     Integer beforeRemainingTimes, Integer afterRemainingTimes, Integer operationType) {
        try {
            UserRechargeRecordDO record = new UserRechargeRecordDO();
            record.setUserId(user.getId());
            record.setUserName(user.getUserName());
            record.setOperationType(operationType);
            record.setBeforeRemainingTimes(beforeRemainingTimes != null ? beforeRemainingTimes : 0);
            record.setOperationTimes(sessionTimes);
            record.setAfterRemainingTimes(afterRemainingTimes != null ? afterRemainingTimes : sessionTimes);
            record.setOperationDesc(operationDesc);
            record.setOperatorId(operatorId);
            record.setOperatorName(operatorName);
            record.setCreateTime(LocalDateTime.now());
            record.setUpdateTime(LocalDateTime.now());

            userRechargeRecordMapper.insert(record);
            String operationTypeDesc = operationType == 1 ? "充值" : "扣款";
            log.info("创建{}记录成功: userId={}, sessionTimes={}, desc={}", operationTypeDesc, user.getId(), sessionTimes, operationDesc);
        } catch (Exception e) {
            throw new RuntimeException("创建充值记录失败: " + e.getMessage());
        }
    }
}
